package net.gz01.wallet.web.controller.admin;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.List;

import javax.imageio.ImageIO;

import com.jfinal.upload.UploadFile;
import net.gz01.util.*;
import net.gz01.wallet.web.config.SystemEnum;
import org.apache.commons.lang3.StringUtils;

import com.jfinal.aop.Before;
import com.jfinal.aop.Duang;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.tx.Tx;

import lombok.extern.slf4j.Slf4j;
import net.gz01.wallet.common.Certificate;
import net.gz01.wallet.common.PageRespon;
import net.gz01.wallet.common.WalletSMS;
import net.gz01.wallet.common.ZOIDGenerate;
import net.gz01.wallet.common.ZOSearchCondition;
import net.gz01.wallet.message.AccountBalanceChangeResp;
import net.gz01.wallet.web.config.SystemConfig;
import net.gz01.wallet.web.config.SystemEnum.BizType;
import net.gz01.wallet.web.config.SystemEnum.OrderStatus;
import net.gz01.wallet.web.config.SystemEnum.Resp;
import net.gz01.wallet.web.controller.BaseController;
import net.gz01.wallet.web.model.Account;
import net.gz01.wallet.web.model.Channel;
import net.gz01.wallet.web.model.Dictionary;
import net.gz01.wallet.web.model.Merch;
import net.gz01.wallet.web.model.MerchUser;
import net.gz01.wallet.web.model.TradeConfig;
import net.gz01.wallet.web.model.TradeOrder;
import net.gz01.wallet.web.model.YouliAccount;
import net.gz01.wallet.web.noitfy.NotifyThread;
import net.gz01.wallet.web.service.AccountService;
import net.gz01.wallet.web.service.CalcFeeService;

@Slf4j
public class ChargeOrderController extends BaseController {

	private CalcFeeService feeService = new CalcFeeService();
	private AccountService accountService = Duang.duang(AccountService.class);

	public void search() {
		setAttr("params", getRequest().getQueryString());
		setAttr("bizTypeList", Dictionary.dao.selectBizType());
		setAttr("orderStatusList", Dictionary.dao.selectOrderStatus());
		render("trade/chargeOrderList.html");
	}

	public void listJson() {
		ZOSearchCondition sc = super.getSearchCondition();
		sc.setParameter("bizType", BizType.Charge.getValue());
		sc.setParameter("bizType2", BizType.Transfer_xx.getValue());
		Page<TradeOrder> pageResult = TradeOrder.dao.search(sc);
		renderJson(new PageRespon(pageResult));
	}

	public void addPage() {
		render("trade/chargeOrderAdd.html");
	}

	public void addPageTemp(){//暂存户充值
		setAttr("tempAccountList", Account.dao.find("select * from account WHERE temp = true"));
		render("trade/chargeOrderAddTemp.html");
	}

	public void add() {
		TradeOrder tradeOrder = getModel(TradeOrder.class);
		TradeConfig config = TradeConfig.dao.selectCharge(tradeOrder.getMerchCode());
		if (config == null) {
			renderFail("充值提交失败,未找到商户充值配置");
			return;
		}

		Account ac = Account.dao.select(tradeOrder.getMerchCode());
		if (ac == null) {
			renderFail("充值提交失败,未找到商户对应的虚账账户");
			return;
		}
		YouliAccount youliAccount = YouliAccount.dao.findById(tradeOrder.getYouliAccountId());
		if (youliAccount == null) {
			renderFail("充值提交失败,未找到商户对应的收款卡信息");
			return;
		}

		BigDecimal amount = new BigDecimal(getPara("amount")).multiply(new BigDecimal(100));
		if (amount.longValue() > 99999999900L) {
			renderFail("充值提交失败,金额超过9亿,请分多笔支付!");
			return;
		}
		// 检查充值的交易配置
		TradeConfig tradeConfig = TradeConfig.dao.selectCharge(tradeOrder.getMerchCode());
		if (tradeConfig == null) {
			renderFail("找不到充值交易配置，请联系管理员");
			return;
		}
		Integer fee = feeService.getFee(amount.intValue(), tradeConfig.getFeeId());
		if (fee < 0) {
			renderFail("费率模式不存在");
			return;
		}
		if (amount.longValue() < fee.longValue()) {
			renderFail("充值(收款)金额不足以支付手续费");
			return;
		}
		// 保存收款(充值)订单
		tradeOrder.setId(ZOIDGenerate.getUUID());
		tradeOrder.setChannelCode(config.getChannelCode());
		tradeOrder.setOrderNo(ZOIDGenerate.getSixOrderNo());
		tradeOrder.setOutOrderNo(tradeOrder.getOrderNo());
		tradeOrder.setFee(fee.longValue());
		tradeOrder.setAmount(amount.longValue());
		tradeOrder.setOrderStatus(OrderStatus.FirstReview.getValue());
		tradeOrder.setCreateTime(ZODate.getDateTime());
		tradeOrder.setBizType(BizType.Charge.getValue());
		tradeOrder.save();
		renderSuccess(tradeOrder.getOrderNo());
	}

	public void addTemp(){
		TradeOrder tradeOrder = getModel(TradeOrder.class);
		Account ac = Account.dao.select(tradeOrder.getMerchCode());
		if (ac == null) {
			renderFail("暂存户充值提交失败,未找到商户对应的虚账账户");
			return;
		}
		tradeOrder.setMerchName(ac.getAccountName());
		tradeOrder.setAccountName(ac.getAccountName());
		tradeOrder.setAccountNo(ac.getAccountNo());
		tradeOrder.setBankName("暂存户");//暂存户
		tradeOrder.setOutAccountName(ac.getAccountName());
		tradeOrder.setOutAccountNo(ac.getAccountNo());
		tradeOrder.setBankName("暂存户");
		BigDecimal amount = new BigDecimal(getPara("amount")).multiply(new BigDecimal(100));
		if (amount.longValue() > 99999999900L) {
			renderFail("暂存户充值提交失败,金额超过9亿,请分多笔支付!");
			return;
		}

		// 保存收款(充值)订单
		tradeOrder.setId(ZOIDGenerate.getUUID());
		tradeOrder.setChannelCode("temp");
		tradeOrder.setOrderNo(ZOIDGenerate.getSixOrderNo());
		tradeOrder.setOutOrderNo(tradeOrder.getOrderNo());
		tradeOrder.setFee(0L);
		tradeOrder.setAmount(amount.longValue());
		tradeOrder.setOrderStatus(OrderStatus.FirstReview.getValue());
		tradeOrder.setCreateTime(ZODate.getDateTime());
		tradeOrder.setBizType(BizType.Charge.getValue());
		tradeOrder.save();
		renderSuccess(tradeOrder.getOrderNo());
	}

	public void firstReviewPage() {
		TradeOrder item = TradeOrder.dao.findById(getPara("id"));
		setAttr("item", item);
		setAttr("channel", Channel.dao.selectByCode(item.getChannelCode()));
		setAttr("merch", Merch.dao.selectByMerchCode(item.getMerchCode()));
		File fileList = new File(SystemEnum.FilePath.Trade.getValue() + item.getOrderNo());
		int num = 0;
		if(fileList!=null && fileList.list()!=null){
			num = fileList.list().length;
		}
		setAttr("fileNum", num);
		setAttr("fileList", fileList.list());
		render("trade/chargeOrderFirstReview.html");
	}

	public void secondReviewPage() {
		TradeOrder item = TradeOrder.dao.findById(getPara("id"));
		setAttr("item", item);
		setAttr("channel", Channel.dao.selectByCode(item.getChannelCode()));
		setAttr("merch", Merch.dao.selectByMerchCode(item.getMerchCode()));
		File fileList = new File(SystemEnum.FilePath.Trade.getValue() + item.getOrderNo());
		int num = 0;
		if(fileList!=null && fileList.list()!=null){
			num = fileList.list().length;
		}
		setAttr("fileNum", num);
		setAttr("fileList", fileList.list());
		render("trade/chargeOrderSecondReview.html");
	}

	/**
	 * 充值(收款)一审
	 */
	@Before(Tx.class)
	public void firstReview() {
		TradeOrder item = TradeOrder.dao.findById(getPara("id"));
		String reviewResult = getPara("reviewResult");
		String purpose = getPara("purpose");
		boolean firstReviewOrderStatus = OrderStatus.FirstReview.getValue().equals(item.getOrderStatus())
				|| OrderStatus.SecondReviewFail.getValue().equals(item.getOrderStatus());
		if (!firstReviewOrderStatus) {
			renderMsg(2, "订单状态错误,不能进行一审操作!");
			return;
		}

		if ("unPass".equals(reviewResult)) {
			String remark = getPara("remark");
			if (StringUtils.isBlank(remark)) {
				renderMsg(2, "审核不通过的备注信息必须填写!");
				return;
			}
			item.setPurpose(remark);
			item.setRespCode(Resp.Fail03.getCode());
			item.setRespMsg(remark);
			item.setOrderStatus(OrderStatus.FirstReviewFail.getValue());
			item.update();

			if(StringUtils.isNotEmpty(item.getNotifyUrl())) {
				//开始异步回调线程
				NotifyThread.getInstance().addNotifyOrder(item);
			}

			renderSuccess("此订单已经审核不通过，请走退款流程!");
			return;
		}

		if ("pass".equals(reviewResult)) {
			if (StringUtils.isBlank(purpose)) {
				renderMsg(2, "审核通过的信息必须填写!");
				return;
			}
			item.setPurpose(purpose);
			item.setRespCode(Resp.Success.getCode());
			item.setRespMsg("一审成功");
			item.setOrderStatus(OrderStatus.SecondReview.getValue());
			item.update();
			renderSuccess("一审成功");
		}
	}

	/**
	 * 充值(收款)二审
	 */
	@Before(Tx.class)
	public void secondReview() {
		TradeOrder item = TradeOrder.dao.findById(getPara("id"));
		String reviewResult = getPara("reviewResult");
		String purpose2 = getPara("purpose2");

		// 二审不通过
		if (OrderStatus.SecondReview.getValue().equals(item.getOrderStatus()) && reviewResult.equals("unPass")) {
			String remark = getPara("remark");
			if (StringUtils.isBlank(remark)) {
				renderMsg(2, "审核不通过的备注信息必须填写!");
				return;
			}
			if(StrKit.notBlank(item.getPurpose2())) {
				item.setPurpose2(item.getPurpose2() +"\n" +
						"二审人员在" + ZODate.getDateTime() +"的审核意见是:" + remark);
			} else {
				item.setPurpose2("二审人员在" + ZODate.getDateTime() +"的审核意见是:" + remark);
			}

			item.setRespCode(Resp.Fail03.getCode());
			item.setRespMsg(remark);
			item.setOrderStatus(OrderStatus.SecondReviewFail.getValue());
			item.update();

			if(StringUtils.isNotEmpty(item.getNotifyUrl())) {
				//开始异步回调线程
				NotifyThread.getInstance().addNotifyOrder(item);
			}

			renderSuccess("此订单已经审核不通过，请通知一审人员继续审核流程!");
			return;
		}

		// 二审通过
		if (OrderStatus.SecondReview.getValue().equals(item.getOrderStatus()) && "pass".equals(reviewResult)) {
			if (StringUtils.isBlank(purpose2)) {
				renderMsg(2, "审核通过的信息必须填写!");
				return;
			}
			Long chargeAmount = Math.abs(item.getAmount()) - Math.abs(item.getFee());
			if (chargeAmount < 0L) {
				item.setRespCode(Resp.Fail.getCode());
				item.setRespMsg("一充值失败:充值金额不够扣手续费");
				item.setOrderStatus(OrderStatus.Fail.getValue());
				item.update();
				renderFail("充值失败:充值金额不够扣手续费");
				return;
			}

			String inputAmt = getPara("inputAmt");
			if(StringUtils.isEmpty(inputAmt)){
				renderMsg(2, "审核通过的核实交易金额必填!");
				return;
			}
			if(!ZOMoney.changeY2F(Double.parseDouble(inputAmt)).equals(""+Math.abs(item.getAmount()))){
				renderMsg(2, "核实交易金额和订单交易金额不一致!");
				return;
			}

			AccountBalanceChangeResp resp = accountService.addMoney(item.getMerchCode(), chargeAmount);

			if ("SUCCESS".equals(resp.getRespCode())) {
				String resMsg = "充值成功";
				if(item.getBizType().equals(BizType.Transfer_xx.getValue())){
					resMsg = "商城消费打款成功";
					NotifyThread.getInstance().addNotifyOrder(item);//异步通知 老铁牛商城这笔线下转账支付成功，可以发货给消费者了。
				}
				if(StringUtils.isNotEmpty(item.getPurpose2())) {
					item.setPurpose2(item.getPurpose2() + "\n" +
							"二审人员在" + ZODate.getDateTime() + "的审核意见是:" + purpose2);
				}else {
					item.setPurpose2("二审人员在" + ZODate.getDateTime() + "的审核意见是:" + purpose2);
				}
				item.setBalance(Long.parseLong(resp.getBalance()));
				item.setOrderStatus(OrderStatus.Success.getValue());
				item.setRespCode(Resp.Success.getCode());
				item.setRespMsg(Resp.Success.getMsg());
				item.setPayTime(ZODate.getDateTime());
				item.setSettleDate(ZODate.getDate());
				//充值成功统一存友利账户
				item.setOutAccountName(item.getAccountName());
				item.setOutAccountNo(item.getAccountNo());
				item.setOutBankName(item.getBankName());

				MerchUser user = MerchUser.dao.selectByMerCode(item.getMerchCode());
				String smsMsg = "通知短信发送失败";
				if(user != null) {
					//发送短信 充值成功
					boolean isOK = WalletSMS.sendSMSAddMenoy(user.getUserName(), Math.abs(item.getAmount()), Long.parseLong(resp.getBalance()));
					if (isOK) {
						smsMsg = "通知短信发送成功";
					}
				}
				try {
					createCertificate(item.getId());
				}catch (Exception e){e.printStackTrace();}

				if(StringUtils.isNotEmpty(item.getNotifyUrl())) {
					//开始异步回调线程
					//异步通知 老铁牛商城这笔线下转账支付成功，可以发货给消费者了。
					NotifyThread.getInstance().addNotifyOrder(item);
				}
				renderSuccess(resMsg + "," + smsMsg);
			} else {
				log.error("人工审核成功，但是资金增加失败:" + ZOJson.toString(item));
				item.setOrderStatus(OrderStatus.Fail.getValue());
				item.setRespCode(Resp.Fail02.getCode());
				item.setRespMsg(Resp.Fail02.getMsg());
				renderFail("充值失败:" + resp.getRespMsg());
			}
			item.update();
		}
	}

	/** 展示电子回单图形 */
	public void certificate() throws Exception {
		File file = new File(SystemConfig.config.get("file_center_path") + "certificate/" + getPara("id") + ".jpg");
		if (file.exists()) {
			renderFile(file);
		} else {
			TradeOrder order = TradeOrder.dao.findById(getPara("id"));
			BufferedImage image = Certificate.createImage(order);
			FileOutputStream fos = new FileOutputStream(file);
			ImageIO.write(image, "jpeg", fos);
			fos.close();
			renderFile(file);
		}
	}


	private void createCertificate(String id) throws Exception {
		File file = new File(SystemConfig.config.get("file_center_path") + "certificate/" + id + ".jpg");
		if (file.exists()) {

		} else {
			TradeOrder order = TradeOrder.dao.findById((id));
			BufferedImage image = Certificate.createImage(order);
			FileOutputStream fos = new FileOutputStream(file);
			ImageIO.write(image, "jpeg", fos);
			fos.close();
		}
	}



//运营端后台上传的文件
	public void uploadFiles() throws Exception {
		List<UploadFile> uploadFile = getFiles();
		log.info("收到的文件个数:" + uploadFile.size());//每次只收到一个文件
		String ordNo = getPara("ordNo");
		log.info("订单号:" + ordNo);
		String newFileName = "";
		for(UploadFile file : uploadFile){
			log.info("文件名字:" + file.getFileName());
			String filename = file.getFileName();
			// 判断文件格式
			if(filename.indexOf('.') == -1) {
				renderFail("文件格式错误");
				return;
			}
			String path = (SystemEnum.FilePath.Trade.getValue() + ordNo);
			ZOFile.mkdir(path);
			File upFile = file.getFile();
			newFileName = (file.getFileName());
			File myfile = new File(SystemEnum.FilePath.Trade.getValue() + ordNo + "/" + newFileName);
			myfile.delete();
			upFile.renameTo(myfile);
			upFile.delete();
		}
		renderSuccess(newFileName);

	}


	public void  viewFiles(){
		String ordNo = getPara("ordNo");
		String fileName = getPara("filename");
		if(StringUtils.isEmpty(fileName) || StringUtils.isEmpty(ordNo)){
			renderText("文件名或者订单号不能为空!");
			return;
		}

		String path = (SystemEnum.FilePath.Trade.getValue() + ordNo);
		File filePath = new File(path);
		if(filePath.exists() && filePath.isDirectory()){
			String[] fileNameList = filePath.list();
			for(String name: fileNameList){
				log.info("查询的文件名字:" + name);
				if(name.equals(fileName)){
					File nameFile = new File(path +"/" + name);
					renderFile(nameFile);
					return;
				}
			}
		}
		renderText("订单号:" + ordNo + "的" + fileName +"文件名不存在!");
	}

}
